

#include "EpollPoller.hpp"
#include "Logger.hpp"
#include "Channel.hpp"
#include <cstring>
#include <unistd.h>

namespace zephyr {

//  channel的成员index_初始化为-1
const int k_New = -1;   // channel 还未添加到poller中
const int k_Added = 1;  // channel 已经添加到poller中
const int k_Deleted = 2; // channel 已经从poller中删除

EpollPoller::EpollPoller(EventLoop *loop)
    : Poller(loop)
    , m_epfd(epoll_create1(EPOLL_CLOEXEC))
    , m_events(k_initEventListSize) { /* vector<epoll_event>(16) */
    if (m_epfd < 0) {
        LOG_FATAL("epoll_create error: %s.\n", strerror(errno));
    }
}


EpollPoller::~EpollPoller() {
    close(m_epfd);
}

// epoll wait
Timestamp EpollPoller::poll(int timeoutMs, ChannelList *activeChannels) {
    LOG_INFO("%s:%d => fd total count: %lu.", __FILE__, __LINE__, m_channels.size());
    int numEvents = epoll_wait(m_epfd, &*m_events.begin(), static_cast<int>(m_events.size()), timeoutMs);
    int saveErrno = errno;
    Timestamp now(Timestamp::now());

    if (numEvents > 0) {
        fillActiveChannels(numEvents, activeChannels);
        if (numEvents == m_events.size()) {
            m_events.resize(m_events.size() * 2);
        }
    } else if (numEvents == 0) {
        // time out
        LOG_DEBUG("%s: timeout.\n", __FUNCTION__);
    } else {
        if (saveErrno != EINTR) {
            errno = saveErrno;
            LOG_ERROR("EpollPoller::poll() error!");
        }
    }

    return now;

}

// channel:: update() remove() --> EventLoop:: updateChannel() removeChannel() --> Poller:: updateChannel() removeChannel()
void EpollPoller::updateChannel(Channel *channel) {
    LOG_INFO("%s:%d => fd = %d, events = %d, index = %d.", __FILE__, __LINE__, channel->fd(), channel->events(), channel->index());
    const int index = channel->index();

    if (index == k_New || index == k_Deleted) {
        if (index == k_New) {
            int fd = channel->fd();
            m_channels[fd] = channel;
        } else {
            //
        }
        channel->setIndex(k_Added);
        update(EPOLL_CTL_ADD, channel);
    } else { // index == k_Added
        int fd = channel->fd();
        if (channel->isNoneEvent()) {
            update(EPOLL_CTL_DEL, channel);
            channel->setIndex(k_Deleted);
        } else {
            update(EPOLL_CTL_MOD, channel);
        }
    }
}


void EpollPoller::removeChannel(Channel *channel) {
    LOG_INFO("%s:%d => fd = %d.\n", __FILE__, __LINE__, channel->fd());
    int fd = channel->fd();
    m_channels.erase(fd);

    int index = channel->index();
    if (index == k_Added) {
        update(EPOLL_CTL_DEL, channel);
    }
    channel->setIndex(k_Deleted);
}

// 填充所有被唤醒的 channel，这样Eventloop 就可以得到所有发生事件的连接
void EpollPoller::fillActiveChannels(int numEvents, ChannelList *activeChannels) const {
    for (int i = 0; i < numEvents; i++) {
        Channel *channel = static_cast<Channel *>(m_events[i].data.ptr);
        channel->set_realEvents(m_events[i].events);
        activeChannels->push_back(channel);
    }
}

//  epoll_ctl 
void EpollPoller::update(int operation, Channel *channel) {
    struct epoll_event event;
    memset(&event, 0, sizeof(event));

    int fd = channel->fd();
    event.events = channel->events();
    event.data.fd = fd; // ???
    event.data.ptr = channel;


    if (epoll_ctl(m_epfd, operation, fd, &event) < 0) {
        if (operation == EPOLL_CTL_DEL) {
            // epoll ctl del error: errno;
            LOG_ERROR("epoll_ctl del error: %s.\n", strerror(errno));
        } else {
            // epoll ctl add/mod error: errno;
            LOG_FATAL("epoll_ctl add/mod error: %s.\n", strerror(errno));
        }
    }
}




}